<!-- 组件瀑布流图片展示 -->
<template>
  <div ref="container" class="clothing-grid" >
    <div
        v-for="(item, index) in items"
        :key="index"
        class="waterfall-item"
        :style="itemStyle(item)"
        @click="clickImage(item)"
    >
      <!--      <img :src="item.src" class="waterfall-img"/>-->
      <el-image class="waterfall-img clothing-card" :src="item.src" lazy/>
    </div>
  </div>
</template>

<script setup>
import {ref, watch, onMounted, onUnmounted} from 'vue'

const props = defineProps({
  images: {
    type: Array,
    required: true
  },
  columnWidth: { // 每列基础宽度
    type: Number,
    default: 300
  },
  gutter: { // 图片间距
    type: Number,
    default: 15
  }
})
const emit = defineEmits(["openDetail"])
/**
 * 传参案例
 * :images="imageList" //imageList=[{src:'地址'},...]
 * :column-width="300" // 每列基础宽度
 * :gutter="15" // 图片间距
 */
const container = ref(null)
const items = ref([])
let resizeObserver = null

const loadImage = (url) => {
  return new Promise((resolve, reject) => {
    const img = new Image()
    img.src = url
    img.onload = () => resolve(img)
    img.onerror = reject
  })
}

const computeLayout = async () => {
  if (!container.value) return

  // 加载所有图片获取原始尺寸
  const imagesData = await Promise.all(
      props.images.map(async (image) => {
        const img = await loadImage(image.src)
        return {
          src: image.src,
          width: img.naturalWidth,
          height: img.naturalHeight,
          clothInfo: image.clothInfo
        }
      })
  )

  const containerWidth = container.value.offsetWidth
  const numColumns = Math.max(
      1,
      Math.floor((containerWidth + props.gutter) / (props.columnWidth + props.gutter))
  )
  const columnHeights = new Array(numColumns).fill(0)
  const newItems = []

  for (const imgData of imagesData) {
    // 计算显示尺寸
    const displayWidth = props.columnWidth
    const displayHeight = (displayWidth / imgData.width) * imgData.height

    // 找到最短列
    const minHeight = Math.min(...columnHeights)
    const columnIndex = columnHeights.indexOf(minHeight)

    // 计算位置
    const left = columnIndex * (props.columnWidth + props.gutter)
    const top = columnHeights[columnIndex]

    newItems.push({
      src: imgData.src,
      left,
      top,
      width: displayWidth,
      height: displayHeight,
      clothInfo: imgData.clothInfo
    })

    // 更新列高度
    columnHeights[columnIndex] += displayHeight + props.gutter
  }

  // 更新容器高度
  container.value.style.height = `${Math.max(...columnHeights) - props.gutter}px`
  items.value = newItems
}

const itemStyle = (item) => ({
  left: `${item.left}px`,
  top: `${item.top}px`,
  width: `${item.width}px`,
  height: `${item.height}px`
})

const clickImage = (res) => {
  emit("openDetail", res)
}
onMounted(() => {
  resizeObserver = new ResizeObserver(() => computeLayout())
  if (container.value) {
    resizeObserver.observe(container.value)
  }
  computeLayout()
})

onUnmounted(() => {
  if (resizeObserver) {
    resizeObserver.disconnect()
  }
})

watch(() => props.images, computeLayout)
watch(() => props.columnWidth, computeLayout)
watch(() => props.gutter, computeLayout)
</script>
